import Utils from '../utils';
import { tts } from '../public';

/**
 * HTML5模式的播放器。<br/><br/>
 *
 * 基于AudioContext技术设计开发，用于支持该环境下的远程音频播放。
 */
const default_player_options = {
    onInit:function (mess) {

    },
    onError: function (err) {

    },
};

class Html5Player {
    /**
     * 创建一个Html5音频播放器。
     * @param {Object} options - 初始化参数。格式参见：
     */
    constructor(options) {
        this.options = null;
        if(options){
            this.options = Utils.extend(options,default_player_options,true);
        }

        if(!this._support_player()){
            return;
        }
        let AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
        this.ctx = new AudioContext();
        if (this.ctx) {
            this.src = this.ctx.createBufferSource();
            this.gain = this.ctx.createGain();
            this.gain.connect(this.ctx.destination);
            this.buff = null;
            this.tts = tts;
            this.can_play = true;
            this.loaded = true;
            if(this.options && typeof this.options.success == "function"){
                this.options.success();
            }
        }else{
            if(this.options && typeof this.options.onError == "function"){
                this.options.onError("Html5Player init fail")
            }
            console.error("Html5Player init fail");
        }
    }

    /**
     * 远程加载音频。
     *
     * @param {Object} options - 加载音频所需的参数。参数有：
     * @param {string} options.url - 要加载的音频URL地址。
     * @param {callback} options.success - 加载音频成功的Callback，格式：() => {}。
     * @param {callback} options.error - 加载音频失败后的Callback，格式：(err) => {}。
     */
    load(options) {
        if (!options.hasOwnProperty('url') || options.url == "") {
            if (typeof options.error == "function") {
                options.error('param: url is missing!');
                console.error('param: url is missing!')
            }
            return;
        }

        let req = new XMLHttpRequest();
        req.open('GET', options.url, true);
        req.responseType = 'arraybuffer';

        req.onload = () => {
            if (req.status !== 200) {
                if (typeof options.error == "function") {
                    options.error("url:" + options.url + "不存在，获取失败。 status: " + req.status);
                    console.error("url:" + options.url + "不存在，获取失败。 status: " + req.status);
                }
                return;
            }

            this.ctx.decodeAudioData(req.response,
                (data) => {
                    this.buff = data;
                    if (typeof options.success == "function") {
                        options.success();
                    }
                },
                (err) => {
                    if (typeof options.error == "function") {
                        options.error(err);
                    }
                    console.error("decodeAudioData" + JSON.stringify(err));
                }
            );
        };

        req.send();
    }

    /**
     * 播放已经加载的音频。
     *
     * @param {Object} options - 播放音频所需的参数。参数有：
     * @param {int=} options.position - 播放位置，默认0。
     * @param {int=} options.duration - 播放时长。
     * @param {callback} options.onStart - 开始播放音频时的Callback，格式：(code, message) => {}。
     * @param {callback} options.onStop - 音频播放完成后的Callback，格式：(code, message) => {}。
     */
    play(options) {
        if (this.buff && this.ctx) {
            this.src = this.ctx.createBufferSource();
            this.src.connect(this.gain);
            this.src.buffer = this.buff;

            if(typeof options.position =="number"&&typeof options.duration == "number"){
                this.src.start(0,options.position/1000,options.duration/1000);
            }else if(typeof options.position =="number" && typeof options.duration != "number"){
                this.src.start(0,options.position/1000);
            }else if(typeof options.position !="number" && typeof options.duration == "number"){
                this.src.start(0,0,options.duration/1000);
            } else {
                this.src.start(0);
            }
            this.src.onended = function() {
                this.src = null;
                if (typeof options.onStop == "function") {
                    options.onStop();
                }
            };

            if (typeof options.onStart == "function") {
                options.onStart();
            }
        } else {
            if (typeof options.error == "function") {
                options.error('play failed. buff or ctx is null.', this.buff, this.ctx);
                console.error('play failed. buff or ctx is null.', this.buff, this.ctx);
            }
        }
    }

    /**
     * 手动停止音频播放。
     */
    stop() {
        if (this.src && this.src.onended != null) {
            this.src.stop();
            this.src = null;
        }

    }

    /**
     * 重置播放器状态。
     */
    reset() {
        this.stop();
    }

    /**
     * 设置播放器播放音量。
     * @param {int} volume - 要设置的音量。 0 ~ 1
     */
    setVolume(volume) {
        if (this.gain) {
            this.gain.connect(this.ctx.destination);
            this.gain.gain.value = volume;
        } else {
            if(this.options && typeof this.options.onError == "function"){
                this.options.onError("context or gain is null");
            }
            console.error("context or gain is null");
        }
    }

    /**
     * 返回播放器播放音量。
     * @result {int} - 播放器当前音量。 0 ~ 1
     */
    getVolume() {
        if (this.gain) {
            this.gain.connect(this.ctx.destination);
            return this.gain.gain.value;
        } else {
            if(this.options && typeof this.options.onError == "function"){
                this.options.onError("context or gain is null");
            }
            console.error("context or gain is null");
            return 0.0;
        }
    }

    /*
    * 销毁播放器接口
    *
    * */

    dispose(){
        if(this.ctx){
            this.ctx.close();
            this.ctx = null;
            this.src = null;
            this.gain = null;
        }
    }


    _support_player(){
        let supported = true;
        let agent = navigator.userAgent.toLowerCase();
        let AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
        if (agent.indexOf("msie") > 0) {
            console.error(`[ Utils.support_h5 ] Can not running HTML5 mode on Internet Explorer. userAgent: ${agent}`);
            supported = false;
        }else if(!AudioContext){
            console.error('[ Utils.support_h5 ] Your Browser does not support window.AudioContext.');
            return false;
        }
        return supported;
    }
}

window.Html5Player = Html5Player;
export default Html5Player;
